const pending = 'pending'
const fulfilled = 'fulfilled'
const rejected = 'rejected'

const execFuncCatchError = (execFunc, value, resolve, reject) => {
    try {
        const result = execFunc(value)
        resolve(result)
    } catch (error) {
        reject(error)
    }
}
class MyPromise {
    constructor(executor) {
        this.status = pending
        this.value = undefined
        this.reason = undefined

        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            queueMicrotask(() => {
                if (this.status !== pending) return
                this.status = fulfilled
                this.value = value
                this.onFulfilledFns.forEach(fn => {
                    fn()
                })
            })

        }
        const reject = (reason) => {
            queueMicrotask(() => {
                if (this.status !== pending) return
                this.status = rejected
                this.reason = reason
                this.onRejectedFns.forEach(fn => {
                    fn()
                })
            })
        }
        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }
    then(onFulfilled = value => value, onRejected = err => { throw err }) {
        return new MyPromise((res, rej) => {
            // 1.状态fulfilled确定下来
            if (this.status === fulfilled) {
                execFuncCatchError(onFulfilled, this.value, res, rej)
            }
            // 2.状态rejected确定下来
            if (this.status === rejected) {
                execFuncCatchError(onRejected, this.reason, res, rej)
            }
            // 3.还不知道状态
            if (this.status === pending) {
                if (onFulfilled) {
                    this.onFulfilledFns.push(() => {
                        execFuncCatchError(onFulfilled, this.value, res, rej)
                    })
                }
                if (onRejected) {
                    this.onRejectedFns.push(() => {
                        execFuncCatchError(onRejected, this.reason, res, rej)
                    })
                }
            }
        })

    }
    catch(onRejected) {
        return this.then(undefined, onRejected)
    }
    finally(onFinally) {
        this.then(() => onFinally(), () => onFinally())
    }
}

const p1 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        reject(111)
    }, 2000)
})

p1.then((res) => {
    console.log('res ' + res);
    throw new Error('出错啦')
}).then((res) => {
    console.log('res ' + res);
}).catch(err => {
    console.log('err ' + err);
    return 111
}).finally((e) => {
    console.log('finally', e);
})

